package com.lzb.compressmaster.utils;

import android.app.Activity;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.lzb.compressmaster.basic.media.MediaInfo;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.HashSet;
import java.util.Set;
import java.lang.ref.WeakReference;

/**
 * 压缩包扫描工具类
 * 用于扫描本地存储中的所有压缩包文件
 */
public class ArchiveScanner {

    private static final String TAG = "ArchiveScanner";

    // 支持的压缩包格式
    private static final List<String> SUPPORTED_ARCHIVE_EXTENSIONS = Arrays.asList(
            "zip", "rar", "7z", "tar", "gz", "bz2", "xz", "tgz", "tbz2", "txz"
    );

    // 需要扫描的目录
    private static final List<String> SCAN_DIRECTORIES = Arrays.asList(
            Environment.getExternalStorageDirectory().getAbsolutePath(),
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(),
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath()
    );

    private static final Handler mainHandler = new Handler(Looper.getMainLooper());

    /**
     * 扫描回调接口
     */
    public interface ScanCallback {
        void onScanStart();

        void onScanProgress(String currentDirectory);

        void onScanComplete(List<MediaInfo> archives);

        void onScanError(String error);
    }

    /**
     * 同步扫描压缩包
     *
     * @return 压缩包列表
     */
    public static List<MediaInfo> scanArchivesSync() {
        List<MediaInfo> archives = new ArrayList<>();
        Set<String> pathSet = new HashSet<>();
        for (String directory : SCAN_DIRECTORIES) {
            File dir = new File(directory);
            if (dir.exists() && dir.isDirectory()) {
                scanDirectory(dir, archives, pathSet);
            }
        }
        archives.sort((a, b) -> a.getName().compareToIgnoreCase(b.getName()));
        return archives;
    }

    /**
     * 异步扫描压缩包
     *
     * @param activity 当前Activity实例
     * @param callback 扫描回调
     */
    public static void scanArchivesAsync(Activity activity, ScanCallback callback) {
        new Thread(() -> {
            try {
                List<MediaInfo> archives = new ArrayList<>();
                Set<String> pathSet = new HashSet<>();

                // 检查Activity是否有效
                if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
                    return;
                }

                postToMainThread(() -> {
                    if (activity != null && !activity.isFinishing() && !activity.isDestroyed() && callback != null) {
                        callback.onScanStart();
                    }
                });

                for (String directory : SCAN_DIRECTORIES) {
                    File dir = new File(directory);
                    if (dir.exists() && dir.isDirectory()) {
                        postToMainThread(() -> {
                            if (activity != null && !activity.isFinishing() && !activity.isDestroyed() && callback != null) {
                                callback.onScanProgress(dir.getAbsolutePath());
                            }
                        });
                        scanDirectory(dir, archives, pathSet);
                    }
                }

                // 按文件名首字母升序排序
                archives.sort((a, b) -> a.getName().compareToIgnoreCase(b.getName()));

                postToMainThread(() -> {
                    if (activity != null && !activity.isFinishing() && !activity.isDestroyed() && callback != null) {
                        callback.onScanComplete(archives);
                    }
                });
            } catch (Exception e) {
                postToMainThread(() -> {
                    if (activity != null && !activity.isFinishing() && !activity.isDestroyed() && callback != null) {
                        callback.onScanError(e.getMessage());
                    }
                });
            }
        }).start();
    }

    /**
     * 异步扫描压缩包（旧版本，已废弃）
     * 
     * @deprecated 使用 {@link #scanArchivesAsync(Activity, ScanCallback)} 替代
     */
    @Deprecated
    public static void scanArchivesAsync(ScanCallback callback) {
        new Thread(() -> {
            try {
                List<MediaInfo> archives = new ArrayList<>();
                Set<String> pathSet = new HashSet<>();

                for (String directory : SCAN_DIRECTORIES) {
                    File dir = new File(directory);
                    if (dir.exists() && dir.isDirectory()) {
                        postToMainThread(() -> callback.onScanProgress(dir.getAbsolutePath()));
                        scanDirectory(dir, archives, pathSet);
                    }
                }

                archives.sort((a, b) -> a.getName().compareToIgnoreCase(b.getName()));
                postToMainThread(() -> callback.onScanComplete(archives));
            } catch (Exception e) {
                postToMainThread(() -> callback.onScanError(e.getMessage()));
            }
        }).start();
    }

    /**
     * 可取消的扫描任务
     */
    public static class ScanTask {
        private final WeakReference<Activity> activityRef;
        private final WeakReference<ScanCallback> callbackRef;
        private volatile boolean isCancelled = false;
        private Thread scanThread;

        public ScanTask(Activity activity, ScanCallback callback) {
            this.activityRef = new WeakReference<>(activity);
            this.callbackRef = new WeakReference<>(callback);
        }

        public void start() {
            scanThread = new Thread(() -> {
                try {
                    List<MediaInfo> archives = new ArrayList<>();
                    Set<String> pathSet = new HashSet<>();

                    // 检查Activity是否有效
                    Activity currentActivity = activityRef.get();
                    if (currentActivity == null || currentActivity.isFinishing() || currentActivity.isDestroyed()) {
                        return;
                    }

                    postToMainThread(() -> {
                        Activity act = activityRef.get();
                        ScanCallback cb = callbackRef.get();
                        if (act != null && !act.isFinishing() && !act.isDestroyed() && cb != null) {
                            cb.onScanStart();
                        }
                    });

                    for (String directory : SCAN_DIRECTORIES) {
                        if (isCancelled) {
                            return;
                        }

                        File dir = new File(directory);
                        if (dir.exists() && dir.isDirectory()) {
                            postToMainThread(() -> {
                                Activity act = activityRef.get();
                                ScanCallback cb = callbackRef.get();
                                if (act != null && !act.isFinishing() && !act.isDestroyed() && cb != null) {
                                    cb.onScanProgress(dir.getAbsolutePath());
                                }
                            });
                            scanDirectory(dir, archives, pathSet);
                        }
                    }

                    if (isCancelled) {
                        return;
                    }

                    // 按文件名首字母升序排序
                    archives.sort((a, b) -> a.getName().compareToIgnoreCase(b.getName()));

                    postToMainThread(() -> {
                        Activity act = activityRef.get();
                        ScanCallback cb = callbackRef.get();
                        if (act != null && !act.isFinishing() && !act.isDestroyed() && cb != null) {
                            cb.onScanComplete(archives);
                        }
                    });
                } catch (Exception e) {
                    if (!isCancelled) {
                        postToMainThread(() -> {
                            Activity act = activityRef.get();
                            ScanCallback cb = callbackRef.get();
                            if (act != null && !act.isFinishing() && !act.isDestroyed() && cb != null) {
                                cb.onScanError(e.getMessage());
                            }
                        });
                    }
                }
            });
            scanThread.start();
        }

        public void cancel() {
            isCancelled = true;
            if (scanThread != null && scanThread.isAlive()) {
                scanThread.interrupt();
            }
        }

        public boolean isRunning() {
            return scanThread != null && scanThread.isAlive();
        }
    }

    /**
     * 创建可取消的扫描任务
     *
     * @param activity 当前Activity
     * @param callback 扫描回调
     * @return ScanTask实例
     */
    public static ScanTask createScanTask(Activity activity, ScanCallback callback) {
        return new ScanTask(activity, callback);
    }

    /**
     * 在主线程执行回调
     *
     * @param runnable 要执行的操作
     */
    private static void postToMainThread(Runnable runnable) {
        mainHandler.post(runnable);
    }

    /**
     * 递归扫描目录中的压缩包文件（带路径去重）
     * @param directory 要扫描的目录
     * @param archives  存放扫描结果的列表
     * @param pathSet   已扫描路径集合（用于去重）
     */
    private static void scanDirectory(File directory, List<MediaInfo> archives, Set<String> pathSet) {
        if (directory == null || !directory.exists()) return;

        File[] files = directory.listFiles();
        if (files == null) return;

        for (File file : files) {
            if (file.isDirectory()) {
                scanDirectory(file, archives, pathSet);
            } else if (isArchiveFile(file)) {
                String absPath = file.getAbsolutePath();
                if (pathSet.add(absPath)) { // 仅第一次出现才加入
                    MediaInfo info = new MediaInfo(
                            absPath,
                            file.getName(),
                            file.length(),
                            file.lastModified(),
                            null,
                            "application/" + getFileExtension(file.getName()).toLowerCase()
                    );
                    archives.add(info);
                    Log.d(TAG, "Found archive: " + absPath);
                }
            }
        }
    }

    /**
     * 判断是否为压缩包文件
     *
     * @param file 文件
     * @return 是否为压缩包
     */
    private static boolean isArchiveFile(File file) {
        if (file == null || !file.isFile()) {
            return false;
        }

        String fileName = file.getName().toLowerCase();
        String extension = getFileExtension(fileName);

        return SUPPORTED_ARCHIVE_EXTENSIONS.contains(extension);
    }

    /**
     * 获取文件扩展名
     *
     * @param fileName 文件名
     * @return 扩展名
     */
    private static String getFileExtension(String fileName) {
        if (fileName == null || fileName.lastIndexOf('.') == -1) {
            return "";
        }
        return fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
    }

    /**
     * 格式化文件大小
     *
     * @param size 字节大小
     * @return 格式化后的字符串
     */
    public static String formatFileSize(long size) {
        if (size <= 0) {
            return "0 B";
        }

        final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));

        return new java.text.DecimalFormat("#,##0.##")
                .format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }

    /**
     * 扫描指定目录
     *
     * @param directoryPath 指定目录路径
     * @return 压缩包列表
     */
    public static List<MediaInfo> scanDirectory(String directoryPath) {
        List<MediaInfo> archives = new ArrayList<>();
        Set<String> pathSet = new HashSet<>();
        File directory = new File(directoryPath);

        if (directory.exists() && directory.isDirectory()) {
            scanDirectory(directory, archives, pathSet);
            // 按文件名首字母升序排序
            archives.sort((a, b) -> a.getName().compareToIgnoreCase(b.getName()));
        }

        return archives;
    }

    /**
     * 获取支持的压缩包格式列表
     *
     * @return 支持的格式列表
     */
    public static List<String> getSupportedFormats() {
        return new ArrayList<>(SUPPORTED_ARCHIVE_EXTENSIONS);
    }

    /**
     * 按文件类型筛选
     *
     * @param archives 压缩包列表
     * @param fileType 文件类型（如zip、rar等）
     * @return 筛选后的列表
     */
    public static List<MediaInfo> filterByType(List<MediaInfo> archives, String fileType) {
        List<MediaInfo> filtered = new ArrayList<>();
        String targetType = fileType.toLowerCase();

        for (MediaInfo archive : archives) {
            String mimeType = archive.getMimeType();
            if (mimeType != null && mimeType.contains(targetType)) {
                filtered.add(archive);
            }
        }

        return filtered;
    }

    /**
     * 按文件大小筛选
     *
     * @param archives 压缩包列表
     * @param minSize  最小文件大小（字节）
     * @param maxSize  最大文件大小（字节）
     * @return 筛选后的列表
     */
    public static List<MediaInfo> filterBySize(List<MediaInfo> archives, long minSize, long maxSize) {
        List<MediaInfo> filtered = new ArrayList<>();

        for (MediaInfo archive : archives) {
            long size = archive.getSize();
            if (size >= minSize && size <= maxSize) {
                filtered.add(archive);
            }
        }

        return filtered;
    }
}